#ifndef FH_QOS_GMAC_H_
#define FH_QOS_GMAC_H_
/*****************************************************************************
 *  Include Section
 *  add all #include here
 *****************************************************************************/
#include <linux/phy.h>
#include <linux/etherdevice.h>
#include <mach/pmu.h>
#include <linux/delay.h>
#include "fh_qos_gmac_dma.h"

/*****************************************************************************
 * Define section
 * add all #define here
 *****************************************************************************/
#define __qos_raw_writeb(v, a) (*(volatile unsigned char *)(a) = (v))
#define __qos_raw_writew(v, a) (*(volatile unsigned short *)(a) = (v))
#define __qos_raw_writel(v, a) (*(volatile unsigned int *)(a) = (v))
#define __qos_raw_readb(a) (*(volatile unsigned char *)(a))
#define __qos_raw_readw(a) (*(volatile unsigned short *)(a))
#define __qos_raw_readl(a) (*(volatile unsigned int *)(a))


#if(0)
#define dwcqos_write(lp, reg, val)					\
	if(reg != 0x200 && reg != 0x204)\
		pr_err("[###########mac] :: write %08x = %08x\n",((void __iomem *)((lp)->baseaddr)) + (reg), val);\
	writel_relaxed((val), ((void __iomem *)((lp)->baseaddr)) + (reg))
#endif

#define dw_readl(dw, name) \
    __qos_raw_readl(&(((struct dw_qos_regs_map *)dw->regs)->name))
#define dw_writel(dw, name, val) \
    __qos_raw_writel((val), &(((struct dw_qos_regs_map *)dw->regs)->name))
#define dw_readw(dw, name) \
    __qos_raw_readw(&(((struct dw_qos_regs_map *)dw->regs)->name))
#define dw_writew(dw, name, val) \
    __qos_raw_writew((val), &(((struct dw_qos_regs_map *)dw->regs)->name))

#define DWCQOS_FOR_EACH_QUEUE(max_queues, queue_num)			\
		for (queue_num = 0; queue_num < max_queues; queue_num++)

#define FH_QOS_ASSERT(expr) if (!(expr)) { \
        printf("Assertion failed! %s:line %d\n", \
        __func__, __LINE__); \
        while (1)   \
           ;       \
        }

#ifndef BIT
#define BIT(x)	(1 << (x))
#endif

#ifndef CACHE_LINE_SIZE
#define CACHE_LINE_SIZE		32
#endif

#define DWCQOS_MAC_RX_POS		BIT(0)
#define DWCQOS_MAC_TX_POS		BIT(1)

#define DWCQOS_DMA_MODE_SWR      BIT(0)
#define DWCQOS_DMA_RDES3_OWN     BIT(31)
#define DWCQOS_DMA_RDES3_INTE    BIT(30)
#define DWCQOS_DMA_RDES3_BUF2V   BIT(25)
#define DWCQOS_DMA_RDES3_BUF1V   BIT(24)

#define DWCQOS_DMA_CH_CTRL_PBLX8       BIT(16)
#define DWCQOS_DMA_CH_TX_TSE           BIT(12)

#define DWCQOS_MTL_TXQ_TXQEN            BIT(3)
#define DWCQOS_MTL_TXQ_TSF              BIT(1)
#define DWCQOS_MTL_TXQ_TTC512           0x00000070
#define DWCQOS_MTL_RXQ_FUP              BIT(3)
#define DWCQOS_MTL_RXQ_FEP              BIT(4)
#define DWCQOS_MTL_RXQ_RSF              BIT(5)

#define DWCQOS_MTL_TXQ_DEBUG_TRCSTS_READ_STATE	BIT(1)
#define DWCQOS_MTL_TXQ_DEBUG_TRCSTS_MASK	(0x3 << 1)
//txq empty
#define DWCQOS_MTL_TXQ_DEBUG_TXQSTS	BIT(4)


#define DWCQOS_MTL_RXQ_DEBUG_ACTIVE_PACKET_POS_MASK		(0x3fff < 16)
#define DWCQOS_MTL_RXQ_DEBUG_RXQSTS_MASK		(0x3 << 4)
#define DWCQOS_MTL_RXQ_DEBUG_RXQSTS_EMPTY	(0)


#define DWCQOS_DMA_TDES2_IOC     BIT(31)
#define DWCQOS_DMA_TDES3_OWN     BIT(31)
#define DWCQOS_DMA_TDES3_FD      BIT(29)
#define DWCQOS_DMA_TDES3_LD      BIT(28)
#define GMAC_TIMEOUT_SEND		(1000)		//10ms

#define DWCQOS_DMA_CH_IE_NIE           BIT(15)
#define DWCQOS_DMA_CH_IE_AIE           BIT(14)
#define DWCQOS_DMA_CH_IE_RIE           BIT(6)
#define DWCQOS_DMA_CH_IE_TIE           BIT(0)
#define DWCQOS_DMA_CH_IE_FBEE          BIT(12)
#define DWCQOS_DMA_CH_IE_RBUE          BIT(7)

#define DWCQOS_DMA_IS_MTLIS             BIT(16)
#define DWCQOS_DMA_IS_MACIS             BIT(17)
#define DWCQOS_DMA_CH_IS_TI            BIT(0)
#define DWCQOS_DMA_CH_IS_RI            BIT(6)
#define DWCQOS_DMA_CH_IS_RBU            BIT(7)


#define DWCQOS_MAC_HW_FEATURE1_TSOEN    BIT(18)
#define DWCQOS_MAC_HW_FEATURE0_RXCOESEL BIT(16)
#define DWCQOS_MAC_HW_FEATURE0_TXCOESEL BIT(14)


#define DWCQOS_HASH_TABLE_SIZE 64
#define DWCQOS_MAC_IS_LPI_INT           BIT(5)
#define DWCQOS_MAC_IS_MMC_INT           BIT(8)
#define DWCQOS_MAC_IS_RXIPIS_INT        BIT(11)
#define DWCQOS_MAC_RXQ_EN               BIT(1)
#define DWCQOS_MAC_MAC_ADDR_HI_EN       BIT(31)
#define DWCQOS_MAC_PKT_FILT_RA          BIT(31)
#define DWCQOS_MAC_PKT_FILT_HPF         BIT(10)
#define DWCQOS_MAC_PKT_FILT_SAF         BIT(9)
#define DWCQOS_MAC_PKT_FILT_SAIF        BIT(8)
#define DWCQOS_MAC_PKT_FILT_DBF         BIT(5)
#define DWCQOS_MAC_PKT_FILT_PM          BIT(4)
#define DWCQOS_MAC_PKT_FILT_DAIF        BIT(3)
#define DWCQOS_MAC_PKT_FILT_HMC         BIT(2)
#define DWCQOS_MAC_PKT_FILT_HUC         BIT(1)
#define DWCQOS_MAC_PKT_FILT_PR          BIT(0)


#define DWCQOS_DMA_RDES1_IPCE    BIT(7)
#define DWCQOS_DMA_RDES3_ES      BIT(15)

#define DWCQOS_DMA_RDES3_ERR_CRC      BIT(24)
#define DWCQOS_DMA_RDES3_ERR_DRIB     BIT(19)
#define DWCQOS_DMA_RDES3_ERR_REV      BIT(20)
#define DWCQOS_DMA_RDES3_ERR_WDT      BIT(22)
#define DWCQOS_DMA_RDES3_ERR_OV      BIT(21)
#define DWCQOS_DMA_RDES3_ERR_GI      BIT(23)

#define DWCQOS_DMA_TDES3_CTXT    BIT(30)
#define DWCQOS_DMA_TDES3_TCMSSV    BIT(26)


#define DWCQOS_DMA_RDES1_PT      0x00000007
#define DWCQOS_DMA_RDES1_PT_UDP  BIT(0)
#define DWCQOS_DMA_RDES1_PT_TCP  BIT(1)
#define DWCQOS_DMA_RDES1_PT_ICMP 0x00000003

#define BUFFER_SIZE_2K	2048
#define BUFFER_SIZE_4K	4096
#define BUFFER_SIZE_8K	8192
#define BUFFER_SIZE_16K	16384

#define MAX_EACH_DESC_XFER_SIZE	16376
#define MAX_EACH_DESC_REV_SIZE	BUFFER_SIZE_2K
#define MAX_TSO_SEGMENT_SIZE	0x20000
#define FORCE_ACTIVE_QUEUE_INDEX	0

#define QOS_PHY_MODE	PHY_INTERFACE_MODE_RMII

#define QOS_GMAC_DEBUG	(NETIF_MSG_DRV | \
			NETIF_MSG_PROBE | \
			NETIF_MSG_LINK | \
			NETIF_MSG_TIMER | \
			NETIF_MSG_IFDOWN | \
			NETIF_MSG_IFUP | \
			NETIF_MSG_RX_ERR | \
			NETIF_MSG_TX_ERR | \
			NETIF_MSG_TX_QUEUED | \
			NETIF_MSG_INTR | \
			NETIF_MSG_TX_DONE | \
			NETIF_MSG_RX_STATUS | \
			NETIF_MSG_PKTDATA | \
			NETIF_MSG_HW | \
			NETIF_MSG_WOL)

//#define RX_DESC_NUM NAPI_POLL_WEIGHT
#define RX_DESC_NUM 256
#define TX_DESC_NUM 256

/* Flow Control defines */
#define FLOW_OFF	0
#define FLOW_RX		1
#define FLOW_TX		2
#define FLOW_AUTO	(FLOW_TX | FLOW_RX)
/****************************************************************************
 * ADT section
 *  add definition of user defined Data Type that only be used in this file  here
 ***************************************************************************/
enum {
	GMAC_SPEED_10M,
	GMAC_SPEED_100M,
};

enum {
	GMAC_DUPLEX_HALF,
	GMAC_DUPLEX_FULL,
};


enum {
	gmac_phyt_reg_basic_ctrl = 0,
	gmac_phyt_reg_basic_status = 1,
	gmac_phyt_reg_phy_id1 = 2,
	gmac_phyt_reg_phy_id2 = 3,
	gmac_phyt_rtl8201_rmii_mode = 16,
	gmac_phyt_ti83848_rmii_mode = 17,
	gmac_phyt_rtl8201_power_saving = 24,
	gmac_phyt_rtl8201_page_select = 31,
	gmac_phyt_ip101g_page_select = 20
};

struct dwcqos_dma_desc {
	u32	desc0;
	u32	desc1;
	u32	desc2;
	u32	desc3;
	u32 rev[4];
}__attribute__((__aligned__(32)));


enum tx_dma_irq_status {
	tx_hard_error = 1,
	tx_hard_error_bump_tc = 2,
	handle_tx_rx = 3,
};

enum rx_frame_status {
	good_frame = 0,
	discard_frame = 1,
	csum_none = 2,
	llc_snap = 4,
};


struct dw_qos_hw_feature{
	u32 feature0;
	u32 feature1;
	u32 feature2;

	u32 tx_fifo_size;
	u32 rx_fifo_size;
	//txq should == tx dma num.(ip required)
	u32 txq_num;
	u32 rxq_num;
	u32 tx_dma_num;
	u32 rx_dma_num;
	u32 tso_flag;
};



struct net_tx_queue {

	struct dw_qos *pGmac;
	unsigned int irq_num;
	char irq_name[10];
	unsigned int id;
 
	void *p_raw_desc;
	struct dwcqos_dma_desc *p_descs;
	//rec skbuf point add
	u32* p_skbuf;
	//rec skbuf point dma add
	u32* tx_skbuff_dma;
	/* DMA Mapped Descriptor areas*/
	u32 descs_phy_base_addr;
	u32 descs_phy_tail_addr;
	u32 desc_size;
	u32 hw_queue_size;
	// u32 desc_idx;
	u32 desc_xfer_max_size;
	//
	u32 mss;
	u32 cur_idx;
	u32 dirty_idx;
	spinlock_t tx_lock;

};


struct net_rx_queue {

	//bind to driver core point.
	struct dw_qos *pGmac;
	unsigned int irq_num;
	char irq_name[10];
	unsigned int id;

	void *p_raw_desc;
	struct dwcqos_dma_desc *p_descs;
	//rec each skbuf vadd, here just use u32 array to rec
	u32* p_skbuf;
	//rec each skbuf padd, here just use u32 array to rec
	u32* rx_skbuff_dma;
	/* DMA Mapped Descriptor areas*/
	u32 descs_phy_base_addr;
	u32 descs_phy_tail_addr;
	u32 desc_size;
	u32 hw_queue_size;
	u32 desc_xfer_max_size;
	u32 cur_idx;
	u32 dirty_idx;

	//struct napi_struct rx_napi ____cacheline_aligned_in_smp;
	spinlock_t rx_lock;
	//u32 desc_idx;

};

struct dw_qos
{
	void __iomem *regs;
	spinlock_t lock;
	unsigned char local_mac_address[6];
	unsigned char common_irq_no;
	unsigned char common_irq_name[10];
	struct fh_gmac_platform_data* priv_data;
	struct clk* clk;
	struct clk* rmii_clk;
	struct device* dev;
	struct net_device* ndev;
	struct platform_device* pdev;
	struct napi_struct napi ____cacheline_aligned_in_smp;
	struct mii_bus *mii;
	struct phy_device *phydev ____cacheline_aligned_in_smp;
	int phyreset_gpio;

	int phy_id;
	int phy_addr;
	int duplex;	
	int speed;
	int link;
	int pause;
	struct dw_qos_hw_feature hw_fea;
	struct net_tx_queue *tx_queue;
	struct net_rx_queue *rx_queue;
	int phy_interface;
	unsigned int active_queue_index;
	__u32 msg_enable;
	//cpy from platform
	int (*phy_sel)(unsigned int sel);
	int (*inf_set)(unsigned int inf);
	struct phy_interface_info *ac_phy_info;
	struct phy_reg_cfg *ac_reg_cfg;
	__u32 flow_ctrl;
	int wolopts;

	struct workqueue_struct *txtimeout_handler_wq;
	struct work_struct txtimeout_reinit;
};

/* Hardware register definitions. */
struct dw_qos_dma_channel_regs{
	u32 control;
	u32 tx_control;
	u32 rx_control;
	u32 reserved_0;
	u32 txdesc_list_haddr;
	u32 txdesc_list_laddr;
	u32 rxdesc_list_haddr;
	u32 rxdesc_list_laddr;
	u32 txdesc_tail_pointer;
	u32 reserved_1;
	u32 rxdesc_tail_pointer;
	u32 txdesc_ring_len;
	u32 rxdesc_ring_len;
	u32 interrupt_enable;
	u32 rx_interrupt_wdt_timer;
	u32 slot_func_control_status;
	u32 reserved_2;
	u32 current_app_txdesc;
	u32 reserved_3;
	u32 current_app_rxdesc;
	u32 current_app_txbuf_haddr;
	u32 current_app_txbuf_laddr;
	u32 current_app_rxbuf_haddr;
	u32 current_app_rxbuf_laddr;
	u32 status;
	u32 reserved_4[2];
	u32 miss_frame_cnt;
	u32 reserved_5[4];
};

struct dw_qos_dma_regs
{
	u32 mode;
	u32 sysbus_mode;
	u32 interrupt_status;
	u32 debug_status0;
	u32 debug_status1;
	u32 debug_status2;
	u32 reserved_0[2];
	u32 tx_ar_ace_control;
	u32 rx_aw_ace_control;
	u32 txrx_awar_ace_control;
	u32 reserved_1[53];
	struct dw_qos_dma_channel_regs chan[8];
};


/* mtl register */
struct dw_qos_mtl_queue_0_regs{
	u32 txq_operation_mode;
	u32 txq_underflow;
	u32 txq_debug;
	u32 reserved_0[2];
	u32 txq_ets_status;
	u32 txq_quantum_weight;
	u32 reserved_1[4];
	u32 interrupt_control_status;
	u32 rxq_operation_mode;
	u32 rxq_missed_packet_overflow_cnt;
	u32 rxq_debug;
	u32 rxq_control;
};

struct dw_qos_mtl_queue_1_regs{
	u32 txq_operation_mode;
	u32 txq_underflow;
	u32 txq_debug;
	u32 reserved_0;
	u32 txq_ets_control;
	u32 txq_ets_status;
	u32 txq_quantum_weight;
	u32 txq_send_slope_credit;
	u32 txq_hi_credit;
	u32 txq_lo_credit;
	u32 reserved_1;
	u32 interrupt_control_status;
	u32 rxq_operation_mode;
	u32 rxq_missed_packet_overflow_cnt;
	u32 rxq_debug;
	u32 rxq_control;
};

struct dw_qos_mtl_regs
{
	u32 operation_mode;
	u32 reserved_0;
	u32 debug_control;
	u32 debug_status;
	u32 fifo_debug_data;
	//doc bug...
	u32 reserved_1[3];

	u32 interrupt_status;
	u32 reserved_2[3];

	u32 rxq_dma_map0;
	u32 rxq_dma_map1;
	u32 reserved_3[50];

	struct dw_qos_mtl_queue_0_regs q_0;
	struct dw_qos_mtl_queue_1_regs q_x[7];
	u32 reserved_4[64];
};


/* mac register */
struct dw_mac_addr{
	u32 addr_hi;
	u32 addr_lo;
};

struct dw_mac_mmc_regs{
	u32 control;
	u32 rx_interrupt;
	u32 tx_interrupt;
	u32 rx_interrupt_mask;
	u32 tx_interrupt_mask;
	u32 tx_octet_cnt_good_bad;
	u32 tx_packet_cnt_good_bad;
	u32 tx_broadcast_packet_good;
	u32 tx_multi_packet_good;
	u32 tx_64_octet_packet_good_bad;
	u32 tx_65_127_octet_packet_good_bad;
	u32 tx_128_255_octet_packet_good_bad;
	u32 tx_256_511_octet_packet_good_bad;
	u32 tx_512_1023_octet_packet_good_bad;
	u32 tx_1024_max_octet_packet_good_bad;
	u32 tx_unicast_packet_good_bad;
	u32 tx_multicast_packet_good_bad;
	u32 tx_broadcast_packet_good_bad;
	u32 tx_underflow_err_packet;
	u32 tx_single_collision_packet;
	u32 tx_multi_collision_packet;
	u32 tx_deferred_packet;
	u32 tx_late_collision_packet;
	u32 tx_excessive_collision_packet;
	u32 tx_carrier_err_packet;
	u32 tx_octet_cnt_good;
	u32 tx_packet_cnt_good;
	u32 tx_excessive_deferral_err;
	u32 tx_pause_packet;
	u32 tx_vlan_packet_good;
	u32 tx_osize_packet_good;
	u32 reserved_0;
	u32 rx_packet_cnt_good_bad;
	u32 rx_octet_cnt_good_bad;
	u32 rx_octet_cnt_good;
	u32 rx_broadcast_packet_good;
	u32 rx_multi_packet_good;
	u32 rx_crc_err_packet;
	u32 rx_align_err_packet;
	u32 rx_runt_err_packet;
	u32 rx_jabber_err_packet;
	u32 rx_undersize_packet_good;
	u32 rx_oversize_packet_good;
	u32 rx_64_octet_packet_good_bad;
	u32 rx_65_127_octet_packet_good_bad;
	u32 rx_128_255_octet_packet_good_bad;
	u32 rx_256_511_octet_packet_good_bad;
	u32 rx_512_1023_octet_packet_good_bad;
	u32 rx_1024_max_octet_packet_good_bad;
	u32 rx_unicase_packet_good;
	u32 rx_len_err_packet;
	u32 rx_out_of_range_type_packet;
	u32 rx_pause_packet;
	u32 rx_fifo_overflow_packet;
	u32 rx_vlan_packet_good_bad;
	u32 rx_wdt_err_packet;
	u32 rx_rev_err_packet;
	u32 rx_control_packet_good;
	u32 reserved_1;
	u32 tx_lpi_micro_sec_timer;
	u32 tx_lpi_trans_cnt;
	u32 rx_lpi_micro_sec_timer;
	u32 rx_lpi_trans_cnt;
	u32 reserved_2;

	u32 mmc_ipc_rx_interrupt_mask;
	u32 reserved_3;
	u32 mmc_ipc_rx_interrupt;
	u32 reserved_4;
	//0x810 TBD........
	u32 reserved_5[60];
};

struct dw_gmac_mac_l3_l4_regs{
	//u32 l3_l4_control;
};


struct dw_qos_mac_regs
{
	u32 config;
	u32 ext_config;
	u32 packet_filter;
	u32 wdt_timeout;
	u32 hash_table_reg[8];
	u32 reserved_0[8];
	u32 vlan_tag;
	u32 reserved_1;
	u32 vlan_hash_table;
	u32 reserved_2;
	u32 vlan_incl;
	u32 inner_vlan_incl;
	u32 reserved_3[2];
	u32 tx_flow_ctrl[8];
	u32 rx_flow_ctrl;
	u32 reserved_4;
	u32 txq_prty_map0;
	u32 txq_prty_map1;
	u32 rxq_ctrl[4];
	u32 interrupt_status;
	u32 interrupt_enable;
	u32 rx_tx_status;
	u32 reserved_5;
	u32 pmt_control_status;
	u32 rwk_packet_filter;
	u32 reserved_6[2];
	u32 lpi_control_status;
	u32 lpi_timers_control;
	u32 lpi_entry_timer;
	u32 us_tic_cnt;
	u32 an_control;
	u32 an_status;
	u32 an_advertisement;
	u32 an_link_partner_ability;
	u32 an_expansion;
	u32 tbi_extended_status;
	u32 phyif_control_status;
	u32 reserved_7[5];
	u32 version;
	u32 debug;
	u32 reserved_8;
	u32 hw_feature_0;
	u32 hw_feature_1;
	u32 hw_feature_2;
	u32 reserved_9[54];
	u32 mdio_addr;
	u32 mdio_data;
	u32 gpio_control;
	u32 gpio_status;
	u32 arp_addr;
	u32 reserved_10[59];
	struct dw_mac_addr mac_addr[128];
	struct dw_mac_mmc_regs mmc;
	//TBD 0x900...
	u32 reserved_11[192];
};

struct dw_qos_regs_map{
	struct dw_qos_mac_regs mac;
	struct dw_qos_mtl_regs mtl;
	struct dw_qos_dma_regs dma;
};


/*****************************************************************************
 *  fun below;
 *****************************************************************************/
void fh_qos_adjust_link(struct net_device *ndev);
void fh_gmac_set_ethtool_ops(struct net_device *netdev);
void fh_qos_tx_flow_process(struct dw_qos *pGmac);
void dwcqos_mac_rx_disable(struct dw_qos *pGmac);
#endif
